package com.yulan.bankback.service.admin.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yulan.bankback.entity.dto.bank.PieChartDto;
import com.yulan.bankback.entity.model.admin.MoneyFlow;
import com.yulan.bankback.entity.model.admin.systemExperience.UserUseTime;
import com.yulan.bankback.entity.model.admin.systemSafe.AttackTypeCount;
import com.yulan.bankback.entity.model.admin.systemSafe.MonthAttack;
import com.yulan.bankback.entity.model.admin.systemSafe.MonthRemoteLogin;
import com.yulan.bankback.entity.model.bank.BankUser;
import com.yulan.bankback.entity.vo.SystemExperienceVo;
import com.yulan.bankback.entity.vo.SystemSafeVo;
import com.yulan.bankback.entity.vo.UserSafeVo;
import com.yulan.bankback.mapper.admin.MoneyFlowMapper;
import com.yulan.bankback.mapper.admin.systemExprience.UserRegionMapper;
import com.yulan.bankback.mapper.admin.systemExprience.UserUseTimeMapper;
import com.yulan.bankback.mapper.admin.systemSafe.*;
import com.yulan.bankback.mapper.bank.BankUserMapper;
import com.yulan.bankback.service.admin.SystemService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SystemServiceImpl implements SystemService {

    @Resource
    private AttackTypeCountMapper attackTypeCountMapper;

    @Resource
    private CityAttackCountMapper cityAttackCountMapper;

    @Resource
    private MonthAttackMapper monthAttackMapper;

    @Resource
    private MoneyFlowMapper moneyFlowMapper;

    @Resource
    private UserRegionMapper userRegionMapper;

    @Resource
    private UserUseTimeMapper userUseTimeMapper;

    @Resource
    private ViolationUserTypeMapper violationUserTypeMapper;

    @Resource
    private MonthRemoteLoginMapper monthRemoteLoginMapper;

    @Resource
    private BankUserMapper bankUserMapper;


    private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd");

    private static final SimpleDateFormat formatter3 = new SimpleDateFormat("MM-dd");



    @Override
    public SystemSafeVo getSystemSafeVo() {
        SystemSafeVo vo = new SystemSafeVo();
        List<AttackTypeCount> attackTypeCounts = attackTypeCountMapper.selectList(new QueryWrapper<>());
        List<PieChartDto<Integer>> attackTpyes = attackTypeCounts.stream()
                .map(item -> new PieChartDto<>(item.getCount() / 10000, item.getAttackType()))
                .collect(Collectors.toList());
        vo.setAttackTypes(attackTpyes);

        List<MonthAttack> oldAttack = monthAttackMapper.selectList(
                new QueryWrapper<MonthAttack>().eq("year", 2019));
        oldAttack.sort((a,b) -> a.getMonth() - b.getMonth());

        List<MonthAttack> newAttack = monthAttackMapper.selectList(
                new QueryWrapper<MonthAttack>().eq("year", 2020));
        newAttack.sort((a,b) -> a.getMonth() - b.getMonth());


        List<Integer> oldData = oldAttack.stream()
                .map(item -> item.getCount() / 10000)
                .collect(Collectors.toList());

        List<Integer> newData = newAttack.stream()
                .map(item -> item.getCount() / 10000)
                .collect(Collectors.toList());

        vo.setNewData(newData);
        vo.setOldData(oldData);
        List<PieChartDto<Integer>> attackRegions = cityAttackCountMapper
                .selectList(new QueryWrapper<>())
                .stream().map(item -> new PieChartDto<>(item.getCount(), item.getCity()))
                .collect(Collectors.toList());
        vo.setAttackRegions(attackRegions);
        return vo;
    }

    @Override
    public SystemExperienceVo getSystemExperienceVo(String interval) {
        SystemExperienceVo vo = new SystemExperienceVo();
        List<MoneyFlow> moneyFlows = moneyFlowMapper.getIntervalMoneyFlow(interval);
        List<UserUseTime> userUseTimes = userUseTimeMapper.getIntervalUserUseTime(interval);
        List<PieChartDto<Integer>> userRegions = userRegionMapper
                .selectList(new QueryWrapper<>())
                .stream().map(item -> new PieChartDto<>(item.getCount() / 1000 , item.getCity()))
                .collect(Collectors.toList());

        List<String> userTimeDate = userUseTimes.stream()
                .map(item -> formatter3.format(item.getTime()))
                .collect(Collectors.toList());

        List<Double> userTimeData = userUseTimes.stream()
                .map(UserUseTime::getUseTime)
                .collect(Collectors.toList());

        List<String> moneyFlowDate = moneyFlows.stream()
                .map(item -> formatter3.format(item.getTime()))
                .collect(Collectors.toList());

        List<Double> moneyFLowData = moneyFlows.stream()
                .map(item -> item.getMoney() / 10000)
                .collect(Collectors.toList());

        while (userTimeDate.size() > 10) userTimeDate = changeListSize(userTimeDate, 4);
        while (moneyFLowData.size() > 10) moneyFLowData = changeListSize(moneyFLowData, 4);
        while (userTimeData.size() > 10) userTimeData = changeListSize(userTimeData, 4);
        while (userTimeDate.size() > 10) userTimeDate = changeListSize(userTimeDate, 4);

        vo.setMoneyFlowData(moneyFLowData);
        vo.setMoneyFlowDate(moneyFlowDate);
        vo.setUserTimeData(userTimeData);
        vo.setUserTimeDate(userTimeDate);
        vo.setUserRegions(userRegions);

        return vo;
    }

    @Override
    public UserSafeVo getUserSafeVo() {
        UserSafeVo vo = new UserSafeVo();
        BankUser bankUser = bankUserMapper.selectOne(
                new QueryWrapper<BankUser>().eq("user_type",1));

        List<Long> oldData = monthRemoteLoginMapper.selectList
                (new QueryWrapper<MonthRemoteLogin>().eq("year", 2019))
                .stream().map(MonthRemoteLogin::getCount)
                .collect(Collectors.toList());
        List<Long> newData = monthRemoteLoginMapper.selectList
                (new QueryWrapper<MonthRemoteLogin>().eq("year", 2020))
                .stream().map(MonthRemoteLogin::getCount)
                .collect(Collectors.toList());

        List<PieChartDto<Long>> violationTypes = violationUserTypeMapper.selectList(
                new QueryWrapper<>()).stream()
                .map(item -> new PieChartDto<>(item.getCount() / 1000, item.getViolationType()))
                .collect(Collectors.toList());

        vo.setSafeScore(bankUser.getSafeScore());
        vo.setNewData(newData);
        vo.setOldData(oldData);
        vo.setViolationUserGroup(violationTypes);
        return vo;
    }

    private <T> List<T> changeListSize(List<T> list, int mod){
        T first = list.get(0);
        T last = list.get(list.size() - 1);

        List<T> res = new ArrayList<>();
        res.add(first);
        for(int i = 1; i < list.size() - 1; i++){
            if(i % mod != 0)
                res.add(list.get(i));
        }
        res.add(last);
        return res;
    }
}
